#ifndef LR_ANALYZER_HPP

#define LR_ANALYZER_HPP

#include <cstdio>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

struct DefineExpr {
  std::string leftItem;
  std::vector<std::string> rightItem;
};

struct ProjectItem {
  int defineExprIndex;
  int pointPos;
  std::string const getId() {
    return std::to_string(defineExprIndex) + std::to_string(pointPos);
  }
};

struct ProjectSet {
  std::unordered_map<std::string, ProjectItem> itemKVs;
  std::unordered_map<std::string, int> convertion;
  std::unordered_set<std::string> kernelSet;
};

class LRAnalyzer {
private:
  bool isNoneTerminal(std::string &s);
  bool isTerminal(std::string s);
  int whereItemExisted(
      std::vector<ProjectSet> &pjSetVec,
      const std::unordered_map<std::string, ProjectItem> &kernelMap);

  std::unordered_map<std::string, ProjectItem>
  getLeftBeginWith(std::string left);

  ProjectSet buildProjectSetFromKernel(
      std::unordered_map<std::string, ProjectItem> &kernelMap);

  void appendProjectSet(std::vector<ProjectSet> &pjSetVec, int targetIndex);

public:
  std::vector<ProjectSet> getProjectSets();

  std::vector<DefineExpr> defineExpresses;
  std::unordered_set<std::string> terminals;
};

#endif // !LR_ANALYZER_HPP
